```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring 依赖注入原理详解</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.8;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background: #2d3748;
            color: #e2e8f0;
            border-radius: 0.5rem;
            position: relative;
        }
        .code-block::before {
            content: attr(data-lang);
            position: absolute;
            top: 0;
            right: 1rem;
            color: #a0aec0;
            font-size: 0.8rem;
            padding: 0.25rem 0.5rem;
            background: rgba(0,0,0,0.2);
            border-radius: 0 0 0 0.5rem;
        }
        .diagram-container {
            background: #f8fafc;
            border-radius: 0.5rem;
            padding: 1.5rem;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }
        .injection-card {
            transition: all 0.3s ease;
            border-left: 4px solid;
        }
        .injection-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .construction {
            border-left-color: #4fd1c5;
        }
        .setter {
            border-left-color: #f6ad55;
        }
        .field {
            border-left-color: #f687b3;
        }
        .drop-cap:first-letter {
            float: left;
            font-size: 3.5rem;
            line-height: 0.8;
            margin: 0.2rem 0.5rem 0 0;
            color: #4c51bf;
            font-weight: 700;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 md:py-32 px-4 md:px-0">
        <div class="container mx-auto max-w-4xl text-center">
            <h1 class="text-4xl md:text-5xl font-bold mb-6">Spring 依赖注入原理详解</h1>
            <p class="text-xl md:text-2xl opacity-90 mb-8">深入解析 Spring 框架核心机制，掌握解耦之道</p>
            <div class="flex justify-center space-x-4">
                <span class="px-4 py-2 bg-white bg-opacity-20 rounded-full text-sm">#Spring框架</span>
                <span class="px-4 py-2 bg-white bg-opacity-20 rounded-full text-sm">#IoC容器</span>
                <span class="px-4 py-2 bg-white bg-opacity-20 rounded-full text-sm">#设计模式</span>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="container mx-auto max-w-4xl px-4 md:px-0 py-12">
        <!-- Introduction -->
        <section class="mb-16">
            <p class="drop-cap text-lg text-gray-700 mb-6">在现代Java企业级开发中，Spring框架因其强大的依赖注入(Dependency Injection)能力而广受欢迎。依赖注入不仅是Spring的核心概念，更是一种优雅的解耦设计模式。</p>
            <p class="text-lg text-gray-700">本文将深入剖析Spring依赖注入的实现原理，从核心接口到具体实现，通过源码解析和可视化图表，帮助开发者全面理解这一重要机制。</p>
        </section>

        <!-- Overview -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-project-diagram mr-3 text-indigo-500"></i> 依赖注入概述
            </h2>
            <div class="grid md:grid-cols-2 gap-8 mb-8">
                <div>
                    <p class="text-gray-700 mb-4">依赖注入(DI)是Spring框架的核心概念之一，其主要目的是解耦组件间的依赖关系。通过依赖注入，Spring可以将一个对象所需要的依赖关系自动注入给它，而不需要对象自己去管理依赖。</p>
                    <p class="text-gray-700">Spring提供了三种主要的依赖注入方式：</p>
                    <ul class="list-disc pl-6 text-gray-700 space-y-2 mt-2">
                        <li><span class="font-medium">构造器注入</span> - 通过构造方法注入依赖</li>
                        <li><span class="font-medium">Setter注入</span> - 通过setter方法注入依赖</li>
                        <li><span class="font-medium">字段注入</span> - 直接通过反射注入字段依赖</li>
                    </ul>
                </div>
                <div class="diagram-container">
                    <div class="mermaid">
                        graph TD
                            A[依赖注入] --> B[构造器注入]
                            A --> C[Setter注入]
                            A --> D[字段注入]
                            B --> E[强制依赖]
                            C --> F[可选依赖]
                            D --> G[简洁但灵活性低]
                    </div>
                </div>
            </div>
        </section>

        <!-- Core Interfaces -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-plug mr-3 text-indigo-500"></i> Spring的核心接口
            </h2>
            <p class="text-gray-700 mb-6">Spring通过<code class="bg-gray-100 px-2 py-1 rounded">BeanFactory</code>和<code class="bg-gray-100 px-2 py-1 rounded">ApplicationContext</code>等接口来管理Bean的生命周期及依赖注入过程。<code class="bg-gray-100 px-2 py-1 rounded">BeanFactory</code>是Spring容器的根接口，它负责Bean的实例化、管理和依赖注入。</p>
            
            <div class="grid md:grid-cols-2 gap-8 mb-8">
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700 flex items-center">
                        <i class="fas fa-code mr-2 text-indigo-400"></i> BeanFactory核心方法
                    </h3>
                    <div class="code-block p-6 mb-4" data-lang="java">
                        <pre><code class="text-sm">public interface BeanFactory {
    Object getBean(String name) throws BeansException;
}</code></pre>
                    </div>
                    <p class="text-gray-700"><code class="bg-gray-100 px-2 py-1 rounded">getBean</code>方法根据给定的名称返回对应的Bean实例，Spring容器会自动处理Bean的依赖注入。</p>
                </div>
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700 flex items-center">
                        <i class="fas fa-sitemap mr-2 text-indigo-400"></i> 接口层级关系
                    </h3>
                    <div class="diagram-container">
                        <div class="mermaid">
                            classDiagram
                                BeanFactory <|-- ApplicationContext
                                BeanFactory : +getBean(String name)
                                ApplicationContext : +getEnvironment()
                                ApplicationContext : +publishEvent(ApplicationEvent event)
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Bean Instantiation -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-cogs mr-3 text-indigo-500"></i> Bean的实例化与依赖注入
            </h2>
            <p class="text-gray-700 mb-6">Spring容器在加载Bean时会根据配置文件或者注解的方式为Bean实例注入所需的依赖。<code class="bg-gray-100 px-2 py-1 rounded">DefaultListableBeanFactory</code>是Spring的默认实现类，负责实例化和管理所有的Bean。</p>
            
            <div class="bg-blue-50 border-l-4 border-blue-400 p-6 rounded-r-lg mb-8">
                <h3 class="text-xl font-semibold mb-4 text-gray-800 flex items-center">
                    <i class="fas fa-info-circle mr-2 text-blue-500"></i> DefaultListableBeanFactory的依赖注入流程
                </h3>
                <div class="code-block p-6 mb-4" data-lang="java">
                    <pre><code class="text-sm">public class DefaultListableBeanFactory extends AbstractBeanFactory {
    @Override
    public Object getBean(String name) throws BeansException {
        // 根据名称获取Bean定义
        BeanDefinition beanDefinition = getBeanDefinition(name);
        
        // 判断是否已经实例化，如果没有则创建新的实例
        if (!beanDefinition.isSingleton()) {
            return createBean(beanDefinition);
        }
        
        return beanDefinition.getBeanClass().newInstance(); // 使用反射创建Bean实例
    }
}</code></pre>
                </div>
                <ul class="list-disc pl-6 text-gray-700 space-y-2">
                    <li><code class="bg-gray-100 px-2 py-1 rounded">getBean</code>方法通过反射创建Bean实例</li>
                    <li>如果Bean的定义为<code class="bg-gray-100 px-2 py-1 rounded">singleton</code>，则返回现有的实例</li>
                    <li>整个过程体现了Spring容器的核心功能：Bean的创建、缓存和管理</li>
                </ul>
            </div>
        </section>

        <!-- Injection Types -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-syringe mr-3 text-indigo-500"></i> 依赖注入的三种方式
            </h2>
            
            <div class="grid md:grid-cols-3 gap-6 mb-8">
                <!-- Construction Injection -->
                <div class="injection-card construction bg-white p-6 rounded-lg shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-teal-100 p-3 rounded-full mr-4">
                            <i class="fas fa-hammer text-teal-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold text-gray-800">构造器注入</h3>
                    </div>
                    <p class="text-gray-700 mb-4">通过调用构造方法来注入Bean的依赖，是最常用的注入方式。</p>
                    <div class="code-block p-4 mb-4" data-lang="java">
                        <pre><code class="text-xs">@Autowired
public MyController(MyService service) {
    this.service = service;
}</code></pre>
                    </div>
                    <div class="bg-teal-50 p-3 rounded-lg">
                        <h4 class="font-medium text-teal-800 mb-2 flex items-center">
                            <i class="fas fa-check-circle mr-2"></i> 优点
                        </h4>
                        <p class="text-sm text-gray-700">强制依赖，保证依赖在实例化时就可用，符合不可变原则。</p>
                    </div>
                </div>
                
                <!-- Setter Injection -->
                <div class="injection-card setter bg-white p-6 rounded-lg shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-orange-100 p-3 rounded-full mr-4">
                            <i class="fas fa-pen-alt text-orange-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold text-gray-800">Setter注入</h3>
                    </div>
                    <p class="text-gray-700 mb-4">通过调用setter方法注入依赖，适用于可选依赖项。</p>
                    <div class="code-block p-4 mb-4" data-lang="java">
                        <pre><code class="text-xs">@Autowired
public void setService(MyService service) {
    this.service = service;
}</code></pre>
                    </div>
                    <div class="bg-orange-50 p-3 rounded-lg">
                        <h4 class="font-medium text-orange-800 mb-2 flex items-center">
                            <i class="fas fa-check-circle mr-2"></i> 优点
                        </h4>
                        <p class="text-sm text-gray-700">更灵活，允许在Bean初始化之后再设置依赖。</p>
                    </div>
                </div>
                
                <!-- Field Injection -->
                <div class="injection-card field bg-white p-6 rounded-lg shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-pink-100 p-3 rounded-full mr-4">
                            <i class="fas fa-tag text-pink-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold text-gray-800">字段注入</h3>
                    </div>
                    <p class="text-gray-700 mb-4">直接通过反射注入字段依赖，代码最简洁。</p>
                    <div class="code-block p-4 mb-4" data-lang="java">
                        <pre><code class="text-xs">@Autowired
private MyService service;</code></pre>
                    </div>
                    <div class="bg-pink-50 p-3 rounded-lg">
                        <h4 class="font-medium text-pink-800 mb-2 flex items-center">
                            <i class="fas fa-check-circle mr-2"></i> 优点
                        </h4>
                        <p class="text-sm text-gray-700">代码简洁，适用于简单场景。</p>
                    </div>
                </div>
            </div>
            
            <div class="bg-yellow-50 border-l-4 border-yellow-400 p-6 rounded-r-lg">
                <h3 class="text-xl font-semibold mb-2 text-gray-800 flex items-center">
                    <i class="fas fa-exclamation-triangle mr-2 text-yellow-600"></i> 字段注入的缺点
                </h3>
                <p class="text-gray-700">虽然字段注入简洁，但它没有强制依赖检查，也无法管理初始化顺序。因此，它一般不推荐用于依赖较多的场景，但对于简单的Bean和短小的依赖链来说非常有效。</p>
            </div>
        </section>

        <!-- Auto-wiring -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-magic mr-3 text-indigo-500"></i> 依赖注入的自动装配方式
            </h2>
            <p class="text-gray-700 mb-6">Spring支持多种自动装配方式：按类型自动装配、按名称自动装配和构造器自动装配。每种方式的实现逻辑有所不同，Spring根据这些装配规则来注入Bean。</p>
            
            <div class="grid md:grid-cols-2 gap-8 mb-8">
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700">按类型自动装配</h3>
                    <p class="text-gray-700 mb-4">按类型自动装配是最常见的一种方式，Spring会根据属性的类型查找符合要求的Bean，并进行注入。</p>
                    <div class="code-block p-6" data-lang="java">
                        <pre><code class="text-sm">public class AutowireCapableBeanFactory {
    public void autowireByType(Object existingBean) {
        // 按类型查找并注入
        for (Field field : existingBean.getClass().getDeclaredFields()) {
            if (field.getType().isAssignableFrom(MyDependency.class)) {
                field.set(existingBean, myDependency);
            }
        }
    }
}</code></pre>
                    </div>
                </div>
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700">按名称自动装配</h3>
                    <p class="text-gray-700 mb-4">按名称自动装配的方式会先根据字段名称查找对应的Bean，然后进行注入。</p>
                    <div class="code-block p-6" data-lang="java">
                        <pre><code class="text-sm">public class AutowireCapableBeanFactory {
    public void autowireByName(Object existingBean) {
        // 按名称查找并注入
        for (Field field : existingBean.getClass().getDeclaredFields()) {
            String fieldName = field.getName();
            if (context.containsBean(fieldName)) {
                field.set(existingBean, context.getBean(fieldName));
            }
        }
    }
}</code></pre>
                    </div>
                </div>
            </div>
            
            <div class="bg-purple-50 border-l-4 border-purple-400 p-6 rounded-r-lg">
                <h3 class="text-xl font-semibold mb-2 text-gray-800">自动装配的选择策略</h3>
                <p class="text-gray-700 mb-2">Spring在选择装配策略时遵循以下优先级：</p>
                <ol class="list-decimal pl-6 text-gray-700 space-y-1">
                    <li>构造器注入（如果有@Autowired标注的构造器）</li>
                    <li>按类型自动装配</li>
                    <li>按名称自动装配</li>
                    <li>使用@Qualifier指定的Bean</li>
                </ol>
            </div>
        </section>

        <!-- Lifecycle Management -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-6 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-life-ring mr-3 text-indigo-500"></i> 依赖注入的生命周期管理
            </h2>
            <p class="text-gray-700 mb-6">Spring对依赖注入的管理不仅限于Bean的初始化，还包括了Bean的生命周期管理。Spring容器可以管理Bean的初始化顺序，确保在依赖注入过程中正确处理Bean的依赖关系。</p>
            
            <div class="grid md:grid-cols-2 gap-8">
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700 flex items-center">
                        <i class="fas fa-cog mr-2 text-indigo-400"></i> BeanPostProcessor的角色
                    </h3>
                    <p class="text-gray-700 mb-4"><code class="bg-gray-100 px-2 py-1 rounded">BeanPostProcessor</code>是Spring提供的一种扩展机制，允许开发者在Bean实例化后、初始化前和初始化后进行自定义操作。它可以用于修改Bean的依赖注入行为，或者为Bean注入额外的功能。</p>
                    <div class="code-block p-6" data-lang="java">
                        <pre><code class="text-sm">public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 在初始化前修改Bean
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 在初始化后修改Bean
        return bean;
    }
}</code></pre>
                    </div>
                </div>
                <div>
                    <h3 class="text-xl font-semibold mb-4 text-gray-700">Bean生命周期流程图</h3>
                    <div class="diagram-container">
                        <div class="mermaid">
                            sequenceDiagram
                                participant C as 容器
                                participant B as Bean
                                C->>B: 实例化Bean
                                C->>B: 填充属性(依赖注入)
                                C->>B: 调用BeanNameAware.setBeanName()
                                C->>B: 调用BeanFactoryAware.setBeanFactory()
                                C->>B: postProcessBeforeInitialization()
                                C->>B: afterPropertiesSet()
                                C->>B: init-method
                                C->>B: postProcessAfterInitialization()
                                C->>B: Bean准备就绪
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Summary -->
        <section class="bg-indigo-50 rounded-xl p-8 mb-16">
            <h2 class="text-2xl font-bold mb-6 text-indigo-800 flex items-center">
                <i class="fas fa-lightbulb mr-3 text-indigo-600"></i> 关键总结
            </h2>
            <div class="grid md:grid-cols-2 gap-6">
                <div>
                    <h3 class="text-lg font-semibold mb-3 text-indigo-700">依赖注入的核心价值</h3>
                    <ul class="list-disc pl-6 text-gray-700 space-y-2">
                        <li>解耦组件间的依赖关系</li>
                        <li>提高代码的可测试性和可维护性</li>
                        <li>统一管理对象的创建和生命周期</li>
                        <li>支持灵活的配置变更</li>
                    </ul>
                </div>
                <div>
                    <h3 class="text-lg font-semibold mb-3 text-indigo-700">最佳实践建议</h3>
                    <ul class="list-disc pl-6 text-gray-700 space-y-2">
                        <li>优先使用构造器注入强制依赖</li>
                        <li>使用Setter注入可选依赖</li>
                        <li>避免过度使用字段注入</li>
                        <li>合理使用@Qualifier解决歧义性</li>
                        <li>了解Spring的自动装配策略</li>
                    </ul>
                </div>
            </div>
        </section>
    </main>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-8">
        <div class="container mx-auto max-w-4xl px-4 md:px-0 text-center">
            <h3 class="text-lg font-medium mb-2">技术小馆</h3>
            <a href="http://www.yuque.com/jtostring" class="text-indigo-400 hover:text-indigo-300 transition-colors">http://www.yuque.com/jtostring</a>
            <div class="mt-4">
                <span class="text-sm opacity-75">© 2023 技术小馆. 保留所有权利.</span>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```